package com.rds.benchmark.connector;

import com.rds.benchmark.config.ArgvsConfig;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.SubscriptionMode;
import org.redisson.config.TransportMode;

public class RedissonConnector implements JedisConnector {

    private RedissonClient redissonClient;
    private String type;

    public RedissonConnector() throws Exception {
        if ("single".equals(ArgvsConfig.mode)) {
            initSingleClient(ArgvsConfig.host, ArgvsConfig.port, ArgvsConfig.threads, ArgvsConfig.password);
        } else if ("sentinel".equals(ArgvsConfig.mode)) {
            initSentinelClient(ArgvsConfig.host, ArgvsConfig.port, ArgvsConfig.threads, ArgvsConfig.sentinelPassword, ArgvsConfig.masterName, ArgvsConfig.password);
        } else if ("cluster".equals(ArgvsConfig.mode)) {
            initClusterClient(ArgvsConfig.host, ArgvsConfig.port, ArgvsConfig.threads, ArgvsConfig.password);
        } else {
            throw new Exception("Connection mode error! allowed values: single,sentinel,cluster. " + " mode=" + ArgvsConfig.mode);
        }
        redissonClient.getBucket("anyBucket").delete();
    }

    private void initSingleClient(String host, int port, int max_threads, String password) {
        Config config = new Config();
        config.useSingleServer()
                .setAddress(
                        "redis://" + host + ":" + port)
                .setIdleConnectionTimeout(10000)
                .setConnectTimeout(10000)
                .setTimeout(30000)
                .setRetryAttempts(3)
                .setRetryInterval(30000)
                .setPassword(password)
                .setClientName(null)
        ;
        config.setThreads(max_threads).setNettyThreads(max_threads * 2).setTransportMode(TransportMode.NIO);
        redissonClient = Redisson.create(config);
        type = "SINGLE";
    }

    private void initSentinelClient(String host, int port, int max_threads, String sentinelPassword, String masterName, String password) {
        Config config = new Config();
        config.useSentinelServers()
                .addSentinelAddress(
                        "redis://" + host + ":" + port)
                .setSentinelPassword(sentinelPassword)
                .setMasterName(masterName)
                .setSubscriptionMode(SubscriptionMode.MASTER)
                .setReadMode(ReadMode.MASTER)
                .setIdleConnectionTimeout(10000)
                .setConnectTimeout(10000)
                .setTimeout(30000)
                .setRetryAttempts(3)
                .setRetryInterval(30000)
                .setPassword(password)
                .setClientName(null)
                .setMasterConnectionMinimumIdleSize(max_threads)
                .setMasterConnectionPoolSize(max_threads)
                .setCheckSentinelsList(false)
        ;
        config.setThreads(max_threads).setNettyThreads(max_threads * 2).setTransportMode(TransportMode.NIO);
        redissonClient = Redisson.create(config);
        type = "SENTINEL";
    }

    public void initClusterClient(final String host, final int port, final int max_threads, final String password) {
        Config config = new Config();
        config.useClusterServers()
                .addNodeAddress(
                        "redis://" + host + ":" + port)
                .setSubscriptionMode(SubscriptionMode.MASTER)
                .setReadMode(ReadMode.MASTER)
                .setIdleConnectionTimeout(10000)
                .setConnectTimeout(10000)
                .setTimeout(30000)
                .setRetryAttempts(3)
                .setRetryInterval(30000)
                .setPassword(password)
                .setClientName(null)
                .setMasterConnectionMinimumIdleSize(max_threads)
                .setMasterConnectionPoolSize(max_threads)
        ;
        config.setThreads(max_threads).setNettyThreads(max_threads * 2).setTransportMode(TransportMode.NIO);
        redissonClient = Redisson.create(config);
        type = "CLUSTER";
    }

    @Override
    public Object getJedis() {
        return redissonClient;
    }

    @Override
    public boolean test() {
        try {
            if (redissonClient.getBucket("anyBucket").trySet("anyValue")) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public String type() {
        return type;
    }
}
